// SPDX-License-Identifier: Mulan PSL v2
/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This software is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

//! 请求重放器实现

use std::collections::VecDeque;
use std::path::Path;
use crc32fast::Hasher;

use crate::ipc::recorder::proto_types::{
    RecordFileHeader, RequestRecord, ArgumentRecord, RecordBatch, ArgumentType
};
use crate::ipc::message::{Request, Argument, ArgumentFlag};

use super::{
    RecorderError, RecordFormat,
    format::{RecordReader, create_reader}
};

/// 请求重放器
pub struct RequestPlayer {
    file_reader: Box<dyn RecordReader>,
    file_header: RecordFileHeader,
    current_position: u64,
    records_cache: VecDeque<RequestRecord>,
    eof_reached: bool,
}

impl RequestPlayer {
    /// 从文件创建重放器
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, RecorderError> {
        Self::from_file_with_format(path, RecordFormat::Protobuf)
    }
    
    /// 从文件创建重放器，指定格式
    pub fn from_file_with_format<P: AsRef<Path>>(path: P, format: RecordFormat) -> Result<Self, RecorderError> {
        let mut file_reader = create_reader(path, format)?;
        let file_header = file_reader.read_header()?;
        
        // 验证文件头部
        Self::validate_header(&file_header)?;
        
        Ok(Self {
            file_reader,
            file_header,
            current_position: 0,
            records_cache: VecDeque::new(),
            eof_reached: false,
        })
    }
    
    /// 读取下一个请求记录
    pub fn next_record(&mut self) -> Result<Option<RequestRecord>, RecorderError> {
        // 如果缓存中有记录，直接返回
        if let Some(record) = self.records_cache.pop_front() {
            self.current_position += 1;
            return Ok(Some(record));
        }
        
        // 如果已到文件末尾，返回None
        if self.eof_reached {
            return Ok(None);
        }
        
        // 从文件读取下一批记录
        match self.file_reader.read_batch()? {
            Some(batch) => {
                // 将批次中的记录加入缓存
                for record in batch.records {
                    self.records_cache.push_back(record);
                }
                
                // 返回第一个记录
                if let Some(record) = self.records_cache.pop_front() {
                    self.current_position += 1;
                    Ok(Some(record))
                } else {
                    Ok(None)
                }
            }
            None => {
                self.eof_reached = true;
                Ok(None)
            }
        }
    }
    
    /// 重建Request对象
    pub fn rebuild_request(&self, record: &RequestRecord) -> Result<Request, RecorderError> {
        // 验证数据完整性
        self.validate_record(record)?;
        
        // 重建参数列表
        let arguments = self.rebuild_arguments(record)?;
        
        // 创建Request对象
        let mut request = Request::new(record.method_id);
        for arg in arguments {
            request.add_argument(arg);
        }
        
        Ok(request)
    }
    
    /// 跳转到指定记录ID
    pub fn seek_to_record(&mut self, record_id: u64) -> Result<(), RecorderError> {
        // 如果目标ID小于当前位置，需要重置到文件开始
        if record_id < self.current_position {
            self.reset()?;
        }
        
        // 顺序查找目标记录
        while let Some(record) = self.next_record()? {
            if record.record_id == record_id {
                // 将找到的记录放回缓存前端
                self.records_cache.push_front(record);
                self.current_position -= 1;
                return Ok(());
            }
        }
        
        Err(RecorderError::InvalidRecord { position: record_id })
    }
    
    /// 按时间戳范围筛选记录
    pub fn filter_by_timestamp(&mut self, start_ns: u64, end_ns: u64) -> Result<Vec<RequestRecord>, RecorderError> {
        let mut filtered_records = Vec::new();
        
        // 重置到文件开始
        self.reset()?;
        
        // 遍历所有记录，筛选时间戳在范围内的记录
        while let Some(record) = self.next_record()? {
            if record.timestamp_ns >= start_ns && record.timestamp_ns <= end_ns {
                filtered_records.push(record);
            }
        }
        
        Ok(filtered_records)
    }
    
    /// 重置到文件开始
    pub fn reset(&mut self) -> Result<(), RecorderError> {
        self.file_reader.seek(0)?;
        
        // 重新读取文件头部
        self.file_header = self.file_reader.read_header()?;
        
        // 清空缓存和状态
        self.records_cache.clear();
        self.current_position = 0;
        self.eof_reached = false;
        
        Ok(())
    }
    
    /// 获取文件头部信息
    pub fn header(&self) -> &RecordFileHeader {
        &self.file_header
    }
    
    /// 获取当前位置
    pub fn position(&self) -> u64 {
        self.current_position
    }
    
    /// 验证文件头部
    fn validate_header(header: &RecordFileHeader) -> Result<(), RecorderError> {
        // 检查魔数
        if header.magic != 0x52455152 {
            return Err(RecorderError::FormatError {
                message: format!("Invalid magic number: 0x{:08x}", header.magic)
            });
        }
        
        // 检查版本兼容性
        if !header.version.starts_with("1.") {
            return Err(RecorderError::FormatError {
                message: format!("Unsupported version: {}", header.version)
            });
        }
        
        Ok(())
    }
    
    /// 验证记录完整性
    fn validate_record(&self, record: &RequestRecord) -> Result<(), RecorderError> {
        // 验证数据校验和
        let mut hasher = Hasher::new();
        hasher.update(&record.raw_data);
        let computed_checksum = hasher.finalize();
        
        if computed_checksum != record.data_checksum {
            return Err(RecorderError::Corruption {
                details: format!(
                    "Checksum mismatch for record {}: expected 0x{:08x}, got 0x{:08x}",
                    record.record_id, record.data_checksum, computed_checksum
                )
            });
        }
        
        Ok(())
    }
    
    /// 重建参数列表
    fn rebuild_arguments(&self, record: &RequestRecord) -> Result<Vec<Argument>, RecorderError> {
        let mut arguments = Vec::new();
        
        for arg_record in &record.arguments {
            let argument = self.rebuild_argument(arg_record, &record.raw_data)?;
            arguments.push(argument);
        }
        
        Ok(arguments)
    }
    
    /// 从ArgumentRecord重建Argument
    fn rebuild_argument(&self, arg_record: &ArgumentRecord, raw_data: &[u8]) -> Result<Argument, RecorderError> {
        let start_offset = arg_record.data_offset as usize;
        let end_offset = start_offset + arg_record.size_bytes as usize;
        
        // 检查边界
        if end_offset > raw_data.len() {
            return Err(RecorderError::FormatError {
                message: format!(
                    "Argument data out of bounds: offset={}, size={}, data_len={}",
                    start_offset, arg_record.size_bytes, raw_data.len()
                )
            });
        }
        
        // 获取参数数据切片
        let arg_data = &raw_data[start_offset..end_offset];
        
        // 转换参数标志
        let flag = self.convert_to_argument_flag(arg_record)?;
        
        // 创建Argument（这里需要处理生命周期问题）
        // 注意：实际使用中需要确保数据的生命周期
        let arg = unsafe {
            Argument::from_raw_parts(
                arg_data.as_ptr() as *const std::ffi::c_void,
                arg_record.size_bytes as usize,
                arg_record.alignment as usize,
                1, // count
                flag,
            )
        };
        
        Ok(arg)
    }
    
    /// 转换为ArgumentFlag
    fn convert_to_argument_flag(&self, arg_record: &ArgumentRecord) -> Result<ArgumentFlag, RecorderError> {
        let mut flag = ArgumentFlag::empty();
        
        if let Some(flags) = &arg_record.flags {
            if flags.is_input {
                flag |= ArgumentFlag::ARG_IN;
            }
            if flags.is_output {
                flag |= ArgumentFlag::ARG_OUT;
            }
        }
        
        // 根据参数类型设置额外标志
        match ArgumentType::try_from(arg_record.arg_type) {
            Ok(ArgumentType::ArgTypeHandle) => {
                flag |= ArgumentFlag::ARG_VIRT;
            }
            _ => {}
        }
        
        Ok(flag)
    }
}

/// 实现Iterator trait以支持迭代
impl Iterator for RequestPlayer {
    type Item = Result<RequestRecord, RecorderError>;
    
    fn next(&mut self) -> Option<Self::Item> {
        match self.next_record() {
            Ok(Some(record)) => Some(Ok(record)),
            Ok(None) => None,
            Err(e) => Some(Err(e)),
        }
    }
}

/// 重放器构建器
#[derive(Default)]
pub struct RequestPlayerBuilder {
    format: Option<RecordFormat>,
    validate_checksums: bool,
    cache_size: usize,
}

impl RequestPlayerBuilder {
    pub fn new() -> Self {
        Self {
            format: None,
            validate_checksums: true,
            cache_size: 1000,
        }
    }
    
    pub fn format(mut self, format: RecordFormat) -> Self {
        self.format = Some(format);
        self
    }
    
    pub fn validate_checksums(mut self, validate: bool) -> Self {
        self.validate_checksums = validate;
        self
    }
    
    pub fn cache_size(mut self, size: usize) -> Self {
        self.cache_size = size;
        self
    }
    
    pub fn build<P: AsRef<Path>>(self, path: P) -> Result<RequestPlayer, RecorderError> {
        let format = self.format.unwrap_or(RecordFormat::Protobuf);
        RequestPlayer::from_file_with_format(path, format)
    }
}

/// 扩展trait：为RequestRecord提供便利方法
pub trait RequestRecordExt {
    /// 获取人类可读的时间戳
    fn timestamp_as_string(&self) -> String;
    
    /// 检查是否包含特定参数类型
    fn has_argument_type(&self, arg_type: ArgumentType) -> bool;
    
    /// 获取参数数量
    fn argument_count(&self) -> usize;
}

impl RequestRecordExt for RequestRecord {
    fn timestamp_as_string(&self) -> String {
        let secs = self.timestamp_ns / 1_000_000_000;
        let nanos = self.timestamp_ns % 1_000_000_000;
        
        if let Ok(dt) = chrono::DateTime::from_timestamp(secs as i64, nanos as u32) {
            dt.format("%Y-%m-%d %H:%M:%S%.9f").to_string()
        } else {
            format!("{}ns", self.timestamp_ns)
        }
    }
    
    fn has_argument_type(&self, arg_type: ArgumentType) -> bool {
        self.arguments.iter().any(|arg| {
            ArgumentType::try_from(arg.arg_type).map_or(false, |t| t == arg_type)
        })
    }
    
    fn argument_count(&self) -> usize {
        self.arguments.len()
    }
}